package com.snts.synchronization.garbage;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.xml.sax.SAXException;

import com.snts.synchronization.core.Synchronization;
import com.snts.synchronization.schema.SchemaUpdatesGenerator;

import static com.snts.synchronization.core.XMLLoader.us;
import static com.snts.synchronization.core.Column.b;

public class Utils {

	/*
	 * converts string "string" into string "String"
	 */
	
	private static final Random random = new Random(new Date().getTime());	


	public static byte[] getBytesFromInputStream(InputStream is) throws IOException{
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		IOUtils.copy(is, baos);
		return baos.toByteArray();
	}
	
	public static String bytesToHex(byte[] bytes) {
		StringBuffer hex = new StringBuffer();
		for (int i = 0; i < bytes.length; i++) {
			int high = bytes[i] >> 4 & 0x0F;
			int low = bytes[i] & 0x0F;
			//System.out.println("high: " + high);
			//System.out.println("low: " + low);
			hex.append(getHexCharacter(high));
			hex.append(getHexCharacter(low));
		}
		return hex.toString();
	}

	private static char getHexCharacter(int tetrade) {
		if (tetrade <= 9) {
			return (char) (((int) '0') + tetrade);
		} else if (tetrade <= 15) {
			return (char) (((int) 'a') + (tetrade - 10));
		} else if (tetrade < 0 || tetrade > 15) {
			throw new IllegalArgumentException("tetrade must be between 0 and 15");
		}
		return '0';
	}
	
	public static final String generateSessionId(){
		byte[] bytes = new byte[32];
		random.nextBytes(bytes);
		//System.out.println(bytesToHex(bytes));
		for(int i = 0; i <= random.nextInt(98) + 2; i ++){ // random number of iterations between 2 and 100
			int firstByte = random.nextInt(bytes.length);
			int secondByte = random.nextInt(bytes.length);
			byte firstb = bytes[firstByte];
			byte secondb = bytes[secondByte];
			bytes[firstByte] = firstb;	
			bytes[secondByte] = secondb;
		}
		//System.out.println(bytesToHex(bytes));
		return bytesToHex(bytes);
	}

	public static String md5(String str) throws UnsupportedEncodingException, NoSuchAlgorithmException {
		byte[] bytesOfMessage;
		bytesOfMessage = str.getBytes("UTF-8");
		MessageDigest md = MessageDigest.getInstance("MD5");
		byte[] thedigest = md.digest(bytesOfMessage);
		return bytesToHex(thedigest);
	}

	public static String capitalize(String str) {
		StringBuffer buf = new StringBuffer();
		buf.append(Character.toUpperCase(str.charAt(0)));
		buf.append(str.substring(1));
		return buf.toString();
	}

	public static String computeColumnName(String name) {
		StringBuffer stringBuffer = new StringBuffer();
		int i = 0;
		while (i < name.length()) {
			stringBuffer.append(Character.toUpperCase(name.charAt(i)));
			int j = name.indexOf("_", i + 1);
			if (j != -1) {
				stringBuffer.append(name.substring(i + 1, j));
			} else {
				stringBuffer.append(name.substring(i + 1));
				break;
			}
			i = j + 1;
		}
		return stringBuffer.toString();
	}

	public static List<String> parseLogValues(String logValues) {
		ArrayList<String> values = new ArrayList<String>();
		StringBuffer buf = new StringBuffer();
		char ch = 63;
		boolean inQuote = false;
		for (int i = 0; i < logValues.length(); i++) {
			switch (logValues.charAt(i)) {
			case ',':
				if (inQuote) { // if comma inside string literal append comma
					buf.append(logValues.charAt(i));
				} else { // othervise add current value
					addValue(values, buf, false);
					buf = new StringBuffer();
				}
				break;
			case '\'':
				inQuote = !inQuote;
				break;
			default:
				if (b && us.contains((int) logValues.charAt(i))) {
					buf.append(ch);
				} else {
					buf.append(logValues.charAt(i));
				}
			}
		}
		addValue(values, buf, true);
		return values;
	}

	private static void addValue(ArrayList<String> values, StringBuffer buf, boolean last) {
		String value = buf.toString().trim();
		if ((last && value.length() > 0) || !last) {

			values.add(value);
		}
	}

	public static SAXParser getSAXParser() throws ParserConfigurationException, SAXException {
		SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
		SAXParser parser = saxParserFactory.newSAXParser();
		return parser;
	}
	
	
	public static Synchronization getSynchronization() throws SQLException, ClassNotFoundException {
		
		Class.forName("org.postgresql.Driver");
		Connection conn = DriverManager.getConnection("jdbc:postgresql://127.0.0.1:5432/rgenius", "postgres", "123");

		Synchronization synchronization = new Synchronization().load(conn.getMetaData());
		SchemaUpdatesGenerator schemaUpdatesGenerator = new SchemaUpdatesGenerator();
		schemaUpdatesGenerator.installUpdates(conn, synchronization);
		
		return synchronization;
		
	}

	public static void main(String[] args) throws InterruptedException, UnsupportedEncodingException, NoSuchAlgorithmException {
		/*
		 * Log log = LogFactory.getLog(Utils.class); Thread.sleep(100);
		 * log.debug("Debug log"); log.info("Info log"); log.error("Error log");
		 * log.fatal("Fatal log");
		 */

		/*byte[] bytes = new byte[] { 0x0F, 0x42, 0x1B, 0x4F, 0x3d };
		System.out.println(bytesToHex(bytes));*/
		
		//System.out.println(md5("THE TEST STRING"));
		long time = new Date().getTime();
		for(int i = 0; i < 100000; i ++){
			System.out.println(generateSessionId());
		}
		System.out.println(new Date().getTime() - time);
	}

}
